home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-01-16 | 51.0 KB | 1,645 lines | [TEXT/MPS ] |
- {------------------------------------------------------------------------------}
- {#}
- {# Apple Macintosh Developer Technical Support}
- {#}
- {# XTND-Capable, MultiFinder-Aware Simple Styled TextEdit Sample Application}
- {#}
- {# XTEStyleSample}
- {#}
- {# XTEStyleSample.p - Pascal Source}
- {#}
- {# Copyright © 1989 Apple Computer, Inc.}
- {# All rights reserved.}
- {#}
- {# Versions: 1.0 10/89}
- {# 2.0 3/91}
- {#}
- {# Components: XTEStyleSample.p March 29, 1991}
- {# XTEStyleSampleGlue.a March 29, 1991}
- {# XTEStyleSample.r March 29, 1991}
- {# XTEStyleSample.h March 29, 1991}
- {# XTEStyleSample.make March 29, 1991}
- {#}
- {# XTEStyleSample is an example application that demonstrates how }
- {# to initialize the commonly used toolbox managers, operate }
- {# successfully under MultiFinder, handle desk accessories and }
- {# create, grow, and zoom windows. Both styled and fundamental TextEdit }
- {# toolbox calls and TextEdit autoscroll are demonstrated. It }
- {# also shows how to create and maintain scrollbar controls as well}
- {# as implementing a basic printing loop. In addition, it has the}
- {# capability to import or export via XTND technology. Thus you can }
- {# save to MacWrite, MS Word, etc. or Open WordPerfect, or other files}
- {# for which you have translators available.}
- {#}
- {# It does not by any means demonstrate all the techniques you }
- {# need for a large application. In particular, XTEStyleSample does not }
- {# cover exception handling, multiple windows/documents, }
- {# sophisticated memory management, or undo. All of }
- {# these are vital parts of a normal full-sized application.}
- {#}
- {# This application is an example of the form of a Macintosh }
- {# application; it is NOT a template. It is NOT intended to be }
- {# used as a foundation for the next world-class, best-selling, }
- {# 600K application. A stick figure drawing of the human body may }
- {# be a good example of the form for a painting, but that does not }
- {# mean it should be used as the basis for the next Mona Lisa.}
- {#}
- {# We recommend that you review this program, TEStyleSample, TESample or Sample before }
- {# beginning a new application. XTEStyleSample is built from TEStyleSample, but}
- {# has the added capability of importing and exporting through the XTND}
- {# architecture. TESample is a simpler version of TEStyleSample}
- {# without styles and Sample is a simple app. which doesn’t }
- {# use TextEdit or the Control Manager.}
- {#}
- {------------------------------------------------------------------------------}
-
-
- PROGRAM XTEStyleSample;
-
- {Segmentation strategy:}
- {}
- { This program consists of three segments. Main contains most of the code,}
- { including the MPW libraries, and the main program. Initialize contains}
- { code that is only used once, during startup, and can be unloaded after the}
- { program starts. %A5Init is automatically created by the Linker to initialize}
- { globals for the MPW libraries and is unloaded right away.}
-
-
- {SetPort strategy:}
- {}
- { Toolbox routines do not change the current port. In spite of this, in this}
- { program we use a strategy of calling SetPort whenever we want to draw or}
- { make calls which depend on the current port. This makes us less vulnerable}
- { to bugs in other software which might alter the current port (such as the}
- { bug (feature?) in many desk accessories which change the port on OpenDeskAcc).}
- { Hopefully, this also makes the routines from this program more self-contained,}
- { since they don't depend on the current port setting.}
-
-
- {Clipboard strategy: }
- {}
- { Under styled TextEdit, TECut and TECopy will write both the text and associated}
- { style information directly to the desk scrap as types 'TEXT' and 'styl'.}
- { Instead of using TEToScrap and TEFromScrap, a new routine TEStylPaste, will }
- { transfer the text and style from the desk scrap to the document. }
-
- {$D+}
-
- USES
- MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, Traps, MacPrint,
- XTNDInterface, XTNDTextTranslator, XTNDPictTranslator, XTEFileIO;
-
- CONST
-
- {kMaxOpenDocuments is used to determine whether a new document can be opened}
- { or created. We keep track of the number of open documents, and disable the}
- { menu items that create a new document when the maximum is reached. If the}
- { number of documents falls below the maximum, the items are enabled again.}
- kMaxOpenDocuments = 10;
-
- {kMinDocDim is used to limit the minimum dimension of a window when GrowWindow}
- { is called.}
- kMinDocDim = 64;
-
- {kControlInvisible is used to 'turn off' controls (i.e., cause the control not}
- { to be redrawn as a result of some Control Manager call such as SetCtlValue)}
- { by being put into the contrlVis field of the record. kControlVisible is used}
- { the same way to 'turn on' the control.}
- kControlInvisible = 0;
- kControlVisible = $FF;
-
- {kMaxTELength is an arbitrary number used to limit the length of text in the TERec}
- { so that various errors won't occur from too many characters in the text.}
- kMaxTELength = 32000;
- (* what about that tech note I wrote? is this a valid check anymore? maw *)
-
- {kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the}
- { SysEnvRec we understand.}
- kSysEnvironsVersion = 1;
-
- {kOSEvent is the event number of the suspend/resume and mouse-moved events sent}
- { by MultiFinder. Once we determine that an event is an osEvent, we look at the}
- { high byte of the message sent to determine which kind it is. To differentiate}
- { suspend and resume events we check the resumeMask bit.}
- kOSEvent = app4Evt; { event used by MultiFinder }
- kSuspendResumeMessage = 1; { high byte of suspend/resume event message }
- kResumeMask = 1; { bit of message field for resume vs. suspend }
- kMouseMovedMessage = $FA; { high byte of mouse-moved event message }
- kNoEvents = 0; {no events mask}
-
- {kMinHeap - This is the minimum result from the following}
- { equation:}
- { }
- { ORD(GetApplLimit) - ORD(ApplicZone)}
- { }
- { for the application to run. It will insure that enough memory will}
- { be around for reasonable-sized scraps, FKEYs, etc. to exist with the}
- { application, and still give the application some 'breathing room'.}
- { To derive this number, we ran under a MultiFinder partition that was}
- { our requested minimum size, as given in the 'SIZE' resource.}
-
- kMinHeap = 29 * 1024;
-
- {kMinSpace - This is the minimum result from PurgeSpace, when called}
- { at initialization time, for the application to run. This number acts}
- { as a double-check to insure that there really is enough memory for the}
- { application to run, including what has been taken up already by}
- { pre-loaded resources, the scrap, code, and other sundry memory blocks.}
-
- kMinSpace = 20 * 1024;
-
- {kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions.}
- kExtremeNeg = -32768;
- kExtremePos = 32767 - 1; { required for old region bug }
-
- {kTESlop provides some extra security when pre-flighting edit commands.}
- kTESlop = 1024;
-
- { The following constants are all menu and item IDs corresponding to their resources }
-
- mApple = 128; { Apple menu }
- iAbout = 1;
-
- mFile = 129; { File menu }
- iNew = 1;
- iOpen = 2; { Added for XTEStyleSample }
- iClose = 4;
- iSave = 5; { Added for XTEStyleSample }
- iSaveAs = 6; { Added for XTEStyleSample }
- iPageSetup = 9; { Added for TEStyleSample }
- iPrint = 10; { Added for TEStyleSample }
- iQuit = 12;
-
- mEdit = 130; { Edit menu }
- iUndo = 1;
- iCut = 3;
- iCopy = 4;
- iPaste = 5;
- iClear = 6;
- iSelectAll = 8; { Added for XTEStyleSample }
-
- mFont = 131; { Font menu-added for XTEStyleSample }
-
- mFontSize = 132; { Font size menu-added for XTEStyleSample }
- iNine = 1;
- iTen = 2;
- iTwelve = 3;
- iFourteen = 4;
- iEighteen = 5;
- iTwoFour = 6;
- iOther = 7;
-
- mStyle = 133; { Style menu-added for XTEStyleSample }
- iPlain = 1;
- iBold = 3;
- iItalic = 4;
- iUnderline = 5;
- iOutline = 6;
- iShadow = 7;
-
- {kDITop and kDILeft are used to locate the Disk Initialization dialogs.}
- kDITop = $0050;
- kDILeft = $0070;
-
- kStyleResType = 'styl';
-
- kNewWindowOffset = 20;
- kWndPosResID = 6;
-
- kTransVersion = 2; { this is the translator version we want }
-
- TYPE
- WindowPosHandle = ^WindowPosPtr;
- WindowPosPtr = ^WindowPosRec;
- WindowPosRec = RECORD
- wndPos: Point;
- wndSize: Point;
- selStart, selEnd, scrollVal, scrollMax: INTEGER;
- END;
-
- VAR
- {The "g" prefix is used to emphasize that a variable is global.}
- gMac: SysEnvRec; { set up by Initialize }
- gHasWaitNextEvent: BOOLEAN; { set up by Initialize }
- gInBackground: BOOLEAN; { maintained by Initialize and DoEvent }
- gFirstMyDlgCall: BOOLEAN; { maintained by Initialize, DoNew, DoOpen, and DoCloseWindow }
-
- {New globals to support printing and style selection }
- gTxStyle: TextStyle; { holds style selected, plain default, maintained by DoMenuCommand }
- gFontName: Str255; { name of font selected, app font default, maintained by DoMenuCommand }
- gFontID: INTEGER; { ID of font selected, app font default, maintained by DoMenuCommand }
- gFontSize: LONGINT; { font size selected, 12 pt default, maintained by DoMenuCommand }
- gPrinterRecord: THPrint; { print handle, maintained by printText }
- gPrinterPort: TPPrPort; { pointer to Print Manager's GrafPort }
-
-
- (*----- windows --------------*)
- gGrayRgn: RgnHandle;
- gDragRect: Rect; (*bounds rect for dragging window*)
- gSizeRect: Rect; (*limits for resizing window*)
- gInitWndPos: Point; (*initial window pos for saved files*)
- gInitScrollVal: INTEGER;
- gInitScrollMax: INTEGER;
- gTotalWindows: longInt; (* Amount to offset new windows by *)
-
-
- (*------- import ----------*)
- gSaveSelected: INTEGER;
- gxtErr, gError: OSErr;
- gTransVersion: INTEGER;
- gTransList: TransDescrHandle;
-
- { Get/Put Import/Export File Routine Declarations }
- { PROCEDURE CallFilter(pAddress: ProcPtr; pParams: Ptr); }
-
- {$S Initialize}
- FUNCTION TrapAvailable (tNumber: INTEGER; tType: TrapType): BOOLEAN;
-
- {Check to see if a given trap is implemented. This is only used by the}
- { Initialize routine in this program, so we put it in the Initialize segment.}
- { The recommended approach to see if a trap is implemented is to see if}
- { the address of the trap routine is the same as the address of the}
- { Unimplemented trap.}
- {Needs to be called after call to SysEnvirons so that it can check}
- { if a ToolTrap is out of range of a pre-MacII ROM.}
- {$IFC UNDEFINED MPW}
- CONST
- _Unimplemented = $A89F;
- {$ENDC}
- BEGIN
- IF (tType = ToolTrap) & (gMac.machineType > envMachUnknown) & (gMac.machineType < envMacII) THEN BEGIN {it's a 512KE, Plus, or SE}
- tNumber := BAND(tNumber, $03FF);
- IF tNumber > $01FF THEN {which means the tool traps}
- tNumber := _Unimplemented; {only go to $01FF}
- END;
- TrapAvailable := NGetTrapAddress(tNumber, tType) <> GetTrapAddress(_Unimplemented);
- END; {TrapAvailable}
-
- {$S Main}
- FUNCTION GetNewFontSize: INTEGER;
- { Display an alert that lets the user choose an unlisted font size }
- CONST
- rFontSelect = 130;
- kSizeItem = 4;
- VAR
- itemHit, theType, oldSize: INTEGER;
- message: Str255;
- sizeDlg: DialogPtr;
- itemHdl: Handle;
- itembox: Rect;
- sizeNum: LONGINT;
- BEGIN { GetNewFontSize }
- oldSize := gFontSize;
- sizeDlg := GetNewDialog(rFontSelect, NIL, WindowPtr(-1));
- IF sizeDlg <> NIL THEN BEGIN
- NumToString(gFontSize, message);
- GetDItem(sizeDlg, kSizeItem, theType, itemHdl, itembox);
- SetIText(itemHdl, message);
- ShowWindow(sizeDlg);
- REPEAT
- ModalDialog(NIL, itemHit);
- UNTIL (itemHit = OK) OR (itemHit = Cancel);
- IF itemHit = OK THEN BEGIN
- GetDItem(sizeDlg, kSizeItem, theType, itemHdl, itembox);
- GetIText(itemHdl, message);
- StringToNum(message, sizeNum);
- GetNewFontSize := sizeNum;
- END
- ELSE
- GetNewFontSize := oldSize;
- DisposDialog(sizeDlg);
- END
- ELSE
- GetNewFontSize := oldSize;
- END; { GetNewFontSize }
-
- {$S Main}
- PROCEDURE AdjustTE (window: WindowPtr);
- { Scroll the TERec around to match up to the potentially updated scrollbar}
- { values. This is really useful when the window resizes such that the}
- { scrollbars become inactive and the TERec had been previously scrolled. }
- VAR
- value: INTEGER;
-
- BEGIN { AdjustTE }
- WITH DocumentPeek(window)^ DO BEGIN
- TEScroll((docTE^^.viewRect.left - docTE^^.destRect.left) - GetCtlValue(docHScroll), (docTE^^.viewRect.top - docTE^^.destRect.top) - GetCtlValue(docVScroll), docTE);
- END; { with }
- END; { AdjustTE }
-
- {$S Main}
- PROCEDURE AdjustScrollSizes (window: WindowPtr);
-
- { Re-calculate the position and size of the viewRect and the scrollbars.}
- { kScrollTweek compensates for off-by-one requirements of the scrollbars}
- { to have borders coincide with the growbox. }
-
- VAR
- teRect: Rect;
-
- BEGIN { AdjustScrollSizes }
- GetTERect(window, teRect); {start with teRect}
- WITH DocumentPeek(window)^, window^.portRect DO BEGIN
- docTE^^.viewRect := teRect;
-
- { AdjustViewRect(docTE) was removed--no longer needed }
-
- MoveControl(docVScroll, right - kScrollbarAdjust, -1);
- SizeControl(docVScroll, kScrollbarWidth, (bottom - top) - (kScrollbarAdjust - kScrollTweek));
- MoveControl(docHScroll, -1, bottom - kScrollbarAdjust);
- SizeControl(docHScroll, (right - left) - (kScrollbarAdjust - kScrollTweek), kScrollbarWidth);
- END; { with }
- END; { AdjustScrollSizes }
-
- {$S Main}
- PROCEDURE AdjustScrollbars (window: WindowPtr; needsResize: BOOLEAN);
-
- { Turn off the controls by jamming a zero into their contrlVis fields }
- { (HideControl erases them and we don't want that). If the controls are to }
- { be resized as well, call the procedure to do that, then call the procedure }
- { to adjust the maximum and current values. Finally re-enable the controls}
- { by jamming a $FF in their contrlVis fields. }
-
- VAR
- oldMax, oldVal: INTEGER;
-
- BEGIN { AdjustScrollbars }
- WITH DocumentPeek(window)^ DO BEGIN
- docVScroll^^.contrlVis := kControlInvisible; { turn them off }
- docHScroll^^.contrlVis := kControlInvisible;
- IF needsResize THEN { move and size if needed }
- AdjustScrollSizes(window);
- AdjustScrollValues(window, NOT needsResize); { fool with max and current value }
- { Now, restore visibility in case we never had to ShowControl during adjustment }
- docVScroll^^.contrlVis := kControlVisible; { turn them on }
- docHScroll^^.contrlVis := kControlVisible;
- END;
- END; { AdjustScrollbars }
-
- {$S Main}
- {$PUSH}
- {$Z+}
- PROCEDURE PascalClikLoop;
-
- { Gets called from our assembly language routine, AsmClikLoop, which is in}
- { turn called by the TEClick toolbox routine. Saves the windows clip region,}
- { sets it to the portRect, adjusts the scrollbar values to match the TE scroll}
- { amount, then restores the clip region. }
-
- VAR
- window: WindowPtr;
- region: RgnHandle;
-
- BEGIN { PascalClikLoop }
- window := FrontWindow;
- region := NewRgn;
- GetClip(region); { save the old clip }
- ClipRect(window^.portRect); { set the new clip }
- AdjustScrollValues(window, TRUE); { pass TRUE for canRedraw }
- SetClip(region); { restore the old clip }
- DisposeRgn(region);
- END; { PascalClikLoop }
- {$POP}
-
- {$S Main}
- {$PUSH}
- {$Z+}
- FUNCTION GetOldClikLoop: ProcPtr;
-
- { Gets called from our assembly language routine, AsmClikLoop, which is in}
- { turn called by the TEClick toolbox routine. It returns the address of the}
- { default clikLoop routine that was put into the TERec by TEAutoView to}
- { AsmClikLoop so ¢t it can call it. }
-
- BEGIN { GetOldClikLoop }
- GetOldClikLoop := DocumentPeek(FrontWindow)^.docClik;
- END; { GetOldClikLoop }
- {$POP}
-
- PROCEDURE AsmClikLoop;
- EXTERNAL;
-
- { A reference to our assembly language routine that gets attached to the clikLoop}
- { field of our TE record. }
-
- (*------------------------------------------------------------------------------*)
- {$S Main}
- PROCEDURE Set_init_position;
- BEGIN { Set_init_position }
- gSelStart := 0;
- gSelEnd := 0;
- gInitWndPos.h := (kNewWindowOffset * gNumDocuments) MOD 172 + 10;
- gInitWndPos.v := (kNewWindowOffset * gNumDocuments) MOD 172 + 45;
- gInitWndSize.h := 400;
- gInitWndSize.v := 300;
- gInitScrollVal := 0;
- gInitScrollMax := 0;
- END; (* Set_init_position *)
-
- (*------------------------------------------------------------------------------*)
- {$S Main}
- PROCEDURE Read_position (prevWDRefNum: INTEGER; prevFileName: Str255);
- VAR
- refNum: INTEGER;
- prevPosHdl: WindowPosHandle;
- BEGIN { Read_position }
- Set_init_position;
-
- refNum := OpenRFPerm(prevFileName, prevWDRefNum, fsRdPerm);
- IF (refNum <> -1) THEN BEGIN
- (* read in window position and selection range *)
- prevPosHdl := WindowPosHandle(Get1Resource(kStyleResType, kWndPosResID));
- IF prevPosHdl <> NIL THEN BEGIN
- HNoPurge(Handle(prevPosHdl));
- IF (PtInRgn(prevPosHdl^^.wndPos, gGrayRgn)) THEN BEGIN
- gSelStart := prevPosHdl^^.selStart;
- gSelEnd := prevPosHdl^^.selEnd;
- gInitWndPos := prevPosHdl^^.wndPos;
- gInitWndSize := prevPosHdl^^.wndSize;
- gInitScrollVal := prevPosHdl^^.scrollVal;
- gInitScrollMax := prevPosHdl^^.scrollMax;
- END;
- END;
- END;
- CloseResFile(refNum);
- END; (* Read_position *)
-
- (*------------------------------------------------------------------------------*)
- {$S Main}
- PROCEDURE ReadFile (myFType: INTEGER; vRefNum: INTEGER; fName: Str255);
- VAR
- error: OSErr;
- fileNumber: INTEGER;
- textLength: LongInt;
- buffPtr: Ptr;
- tempRect: Rect;
- BEGIN
- Read_position(vRefNum, fName);
- DoNew;
- SetWTitle(gTheActiveWindow, fName); (*set correct window title*)
- DocumentPeek(gTheActiveWindow)^.WDRefNum := vRefNum;
- DocumentPeek(gTheActiveWindow)^.fileName := fName;
-
- error := FSOpen(fName, vRefNum, fileNumber); (*open disk file*)
- error := GetEOF(fileNumber, textLength); (*find length of data in file*)
- IF (textLength > $7FFF) THEN
- textLength := $7FFF; (*only read first 32k of text*)
- error := SetFPos(fileNumber, fsFromStart, 0); (*set mark at beginning of file*)
- buffPtr := NewPtr(textLength);
- error := FSRead(fileNumber, textLength, buffPtr);
- error := FSClose(fileNumber); (*close file for safety*)
- TESetText(buffPtr, textLength, gTextH);
- DisposPtr(buffPtr); (*garbage collect*)
-
- TECalText(gTextH); (*calc line starts in TERecord*)
- TESetSelect(gSelStart, gSelEnd, gTextH); (*Set insertion point*)
- SetRect(tempRect, 0, 0, 0, 0);
- ClipRect(tempRect); (* Close clipping region to remove flicker *)
- AdjustScrollValues(gTheActiveWindow, TRUE);
- AdjustTE(gTheActiveWindow);
- ClipRect(gTheActiveWindow^.portRect);
- InvalRect(gTheActiveWindow^.portRect);
- END; (* ReadFile *)
-
- FUNCTION MyDlgHook (theItem: INTEGER; theDialog: DialogPtr; CFP: SFParamBlock; VAR changedFlag: Boolean; unused: LongInt): INTEGER;
- BEGIN
- IF theItem = 6 THEN
- IF gFirstMyDlgCall THEN BEGIN
- CFP.AllowFlags := allowText;
- changedFlag := TRUE;
- gFirstMyDlgCall := FALSE;
- END;
- MyDlgHook := theItem;
- END; (* MyDlgHook *)
-
- {$S Main}
- PROCEDURE BigBadError (error: INTEGER);
- BEGIN
- AlertUser(error,0);
- ExitToShell;
- END;
-
- {$S Initialize}
- PROCEDURE Initialize;
-
- { Set up the whole world, including global variables, Toolbox managers,}
- { menus, and a single blank document.}
-
- {If an error is detected, instead of merely doing an ExitToShell,}
- { which leaves the user without much to go on, we call AlertUser, which puts}
- { up a simple alert that just says an error occurred and then calls ExitToShell.}
- { Since there is no other cleanup needed at this point if an error is detected,}
- { this form of error- handling is acceptable. If more sophisticated error recovery}
- { is needed, an exception mechanism, such as is provided by Signals, can be used.}
- CONST
- { ———— Defines for XTND resources ———— }
- clarisNames = 25003; { Claris names STR# resource }
- clarisFolder = 1;
- xtndNames = 25004; { XTND names STR# resource }
- clarisTranslators = 1;
- xtndSystem = 2;
- VAR
- menuBar: Handle;
- total, contig: LongInt;
- ignoreResult: BOOLEAN;
- event: EventRecord;
- count, ignoreError: INTEGER;
- XTNDSystemName,
- ClarisFolderName: Str255;
-
- BEGIN { Initialize }
- gInBackground := FALSE;
-
- InitGraf(@thePort);
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(NIL);
- InitCursor;
-
- FOR count := 1 TO 3 DO
- ignoreResult := EventAvail(everyEvent, event);
- ignoreError := SysEnvirons(kSysEnvironsVersion, gMac);
- IF gMac.machineType < 0 THEN
- BigBadError(eWrongMachine);
- gHasWaitNextEvent := TrapAvailable(_WaitNextEvent, ToolTrap);
-
- IF ORD(GetApplLimit) - ORD(ApplicZone) < kMinHeap THEN
- BigBadError(eSmallSize);
- PurgeSpace(total, contig);
- IF total < kMinSpace THEN
- IF UnloadScrap <> noErr THEN
- BigBadError(eNoMemory)
- ELSE BEGIN
- PurgeSpace(total, contig);
- IF total < kMinSpace THEN
- BigBadError(eNoMemory);
- END; { if }
-
- menuBar := GetNewMBar(rMenuBar); { read menus into menu bar }
- IF menuBar = NIL THEN
- BigBadError(eNoMemory);
- SetMenuBar(menuBar); { install menus }
- DisposHandle(menuBar);
- AddResMenu(GetMHandle(mApple), 'DRVR'); { add DA names to Apple menu }
- AddResMenu(GetMHandle(mFont), 'FONT'); { add Font names to Font Menu }
- DrawMenuBar;
- gNumDocuments := 0;
-
- { do other initialization here }
- { set up printer stuff-this will allow the default pageSetup parameters to be used, so if}
- { the used decides to print with out using pageSetup everything will be okay }
-
- gPrinterRecord := THPrint(NewHandle(SizeOF(TPrint))); {allocate a print record}
- IF gPrinterRecord <> NIL THEN BEGIN {if we're successful then setup the default settings}
- PrOpen; {open the record }
- PrintDefault(gPrinterRecord); { load in default settings }
- PrClose; { close it up }
- END; { if }
-
- { one-time initialization of the XTND Library… }
- GetIndString(XTNDSystemName, xtndNames, xtndSystem);
- GetIndString(ClarisFolderName, clarisNames, clarisFolder);
-
- gxtErr := XTNDInitTranslators(kTransVersion, XTNDSystemName, ClarisFolderName);
- IF gxtErr <> noErr THEN BEGIN
- AlertUser(eNoXTND,gxtErr);
- gXTNDAvail := FALSE;
- END
- ELSE BEGIN
- gXTNDAvail := TRUE;
- gMyFileType[1].Version := 2;
- gMyFileType[1].TranslatorType := 'FLTI';
- gMyFileType[1].CodeResID := 0;
- gMyFileType[1].FDIFResID := -1;
- gMyFileType[1].NumVersBytes := 0;
- gMyFileType[1].PathLength := 0;
- gMyFileType[1].Flags := 0;
- gMyFileType[1].NumMatches := 1;
- gMyFileType[1].Matches[0].DocCreator := 'XTND';
- gMyFileType[1].Matches[0].DocType := 'TEXT';
- gMyFileType[1].Matches[0].ExactMatch := FALSE;
- gMyFileType[1].Matches[0].creatorAndTypeMask := 0;
- gMyFileType[1].Name := 'Text';
- Load_stored := 1;
- Save_stored := 1;
- END;
-
- DoNew; { create a single empty document }
- END; {Initialize}
-
- {$S Main}
- PROCEDURE PrintText (hTE: TEHandle);
-
- { Prints the edit record. Opens a printer port, calculates the numbers of lines}
- { per page (it may be different for each page depending on the the text styles) and}
- { then calls TEUpdate for the page, scroll a page and TEUpdate, etc. }
-
- CONST
- Margins = 20; { page margins }
-
- VAR
- totalLines: INTEGER; { number of lines in text }
- rView: Rect; { viewRect for TERect }
- oldPort: grafPtr; { hold original grafPtr }
- oldView: Rect; { hold original viewRect }
- oldDest: Rect; { hold original destRect }
- totalHeight: INTEGER; { lineHeight for TERec }
- currentLine: INTEGER; { what line are we on }
- scrollAmount: INTEGER; { how much we scroll by }
- zeroRect: Rect; { 0,0,0,0 rect used in clipRect }
-
- thePrinterStatus: TPrStatus; { printer status }
- openPrintManager: BOOLEAN; { flag if print manager can be opened okay }
- abort: BOOLEAN; { flag if cmd-period is hit to exit routine }
- viewHeight: INTEGER; { temp that has the viewRect height+1 to test conditions }
-
- BEGIN { PrintText }
- OpenPrintManager := FALSE; {printer not open yet}
- IF gPrinterRecord <> NIL THEN BEGIN { do we have a legitimate record?}
- PrOpen; {open mr. print record if okay}
- IF PrJobDialog(gPrinterRecord) THEN BEGIN {bring up job dialog}
- GetPort(oldPort); { save the old stuff to restore later }
- oldView := hTE^^.viewRect;
- oldDest := hTE^^.destRect;
- gPrinterPort := PrOpenDoc(gPrinterRecord, NIL, NIL);
- OpenPrintManager := (PrError = noErr);
- END; { if }
- END; { if }
-
- IF OpenPrintManager THEN BEGIN
- SetPort(grafPtr(gPrinterPort)); { printer port is now the current port }
- SetRect(zeroRect, 0, 0, 0, 0);
-
- rView := gPrinterRecord^^.PrInfo.rPage; { get the size of the page rectangle }
- InsetRect(rView, Margins, Margins); { adjust it for the margins }
- hTE^^.inPort := GrafPtr(gPrinterPort); { force TE to look at the printer port }
- hTE^^.destRect := rView;
- hTE^^.viewRect := rView; { set new view and dest rects to the TERec }
- TECalText(hTE); { recalculate our lineStarts array with the new rects }
- totalLines := hTE^^.nLines; { get the number of lines in the newly sized TERec }
- totalHeight := TEGetHeight(totalLines, 0, hTE);
- hTE^^.destRect.bottom := hTE^^.destRect.top + totalHeight; { how tall our destRect is }
-
- abort := FALSE;
- currentLine := 1; { TextEdit sez that TEGetHeight is 1 not 0 based }
-
- WHILE (NOT (abort) AND (currentLine <= totalLines)) DO BEGIN
- PrOpenPage(gPrinterPort, NIL);
- scrollAmount := 0;
- ClipRect(gPrinterRecord^^.PrInfo.rPage); { Open clipping so text will be drawn }
-
- viewHeight := hTE^^.viewRect.bottom - hTE^^.viewRect.top + 1;
-
- { figure out how many lines there are per page }
- WHILE (((scrollAmount + TEGetHeight(currentLine, currentLine, hTE)) <= viewHeight) AND (currentLine <= totalLines)) DO BEGIN
- scrollAmount := scrollAmount + TEGetHeight(currentLine, currentLine, hTE);
- currentLine := currentLine + 1;
- END; { while }
-
- hTE^^.viewRect.bottom := scrollAmount + Margins; { Add margins since top has a margin }
- TEDeactivate(hTE); { Deactive the edit record so we don't print the cursor or selection range }
- TEUpdate(hTE^^.viewRect, hTE); { print the page }
- ClipRect(zeroRect); { Close clipping so that TEScroll doesn't redraw the text }
- TEScroll(0, -scrollAmount, hTE); { scroll the page so we can print the next one }
- hTE^^.viewRect.bottom := rView.bottom; { reset bottom to full page }
-
- IF prError = iPrAbort THEN
- abort := TRUE;
- PrClosePage(gPrinterPort); { close everything up }
- END; { while }
-
- PrCloseDoc(gPrinterPort);
- IF (gPrinterRecord^^.prJob.bJDocLoop = bSpoolLoop) AND (PrError = noErr) THEN
- PrPicFile(gPrinterRecord, NIL, NIL, NIL, thePrinterStatus);
- PrClose;
- SetPort(oldPort);
- hTE^^.inPort := oldPort;
- hTE^^.viewRect := oldView; { restore the old stuff when we are done }
- hTE^^.destRect := oldDest;
- TEUpdate(hTE^^.viewRect, hTE); { update everything after resetting the port }
- END; { if }
- END; { PrintText }
-
- {$S Main}
- PROCEDURE Terminate;
-
- { Clean up the application and exit. We close all of the windows so that}
- { they can update their documents, if any. }
-
- VAR
- aWindow: WindowPtr;
- closed: BOOLEAN;
-
- BEGIN { Terminate }
- closed := TRUE;
- REPEAT
- aWindow := FrontWindow; { get the current front window }
- IF aWindow <> NIL THEN
- closed := DoCloseWindow(aWindow); { close this window }
- UNTIL (NOT closed) | (aWindow = NIL); { do all windows }
- IF closed THEN
- ExitToShell; { exit if no cancellation }
- END; { Terminate }
-
- {$S Main}
- PROCEDURE AdjustMenus;
-
- VAR
- window: WindowPtr;
- menu: MenuHandle;
- offset: LONGINT;
- undo: BOOLEAN; { flag to enable/disable undo command }
- cutCopyClear: BOOLEAN; { flag to enable/disable editing commands }
- paste: BOOLEAN;
- selectAll: BOOLEAN;
-
- doPrint: BOOLEAN; { flag to enable/disable printing item }
-
- te: TEHandle; { local te handle }
- mode: INTEGER; { current style }
-
- BEGIN
- window := FrontWindow;
-
- menu := GetMHandle(mFile);
- IF gNumDocuments < kMaxOpenDocuments THEN BEGIN
- EnableItem(menu, iNew);{ New is enabled when we can open more documents }
- EnableItem(menu, iOpen);{ Open is enabled when we can open more documents }
- END
- ELSE BEGIN
- DisableItem(menu, iOpen);
- DisableItem(menu, iNew);
- END;
-
- IF window <> NIL THEN BEGIN { Close/Save are enabled when there is a window to close }
- EnableItem(menu, iClose);
- EnableItem(menu, iSave);
- EnableItem(menu, iSaveAs);
- END
- ELSE BEGIN
- DisableItem(menu, iClose);
- DisableItem(menu, iSave);
- DisableItem(menu, iSaveAs);
- END;
-
- menu := GetMHandle(mEdit);
- undo := FALSE;
- cutCopyClear := FALSE;
- paste := FALSE;
- selectAll := FALSE;
- doPrint := FALSE;
-
- IF IsDAWindow(window) THEN BEGIN
- undo := TRUE; { all editing is enabled for DA windows }
- cutCopyClear := TRUE;
- paste := TRUE;
- selectAll := TRUE;
- END
- ELSE IF IsAppWindow(window) THEN BEGIN
- WITH DocumentPeek(window)^.docTE^^ DO
- IF selStart < selEnd THEN BEGIN
- cutCopyClear := TRUE;
- END; { if }
- { Cut, Copy, and Clear is enabled for app. windows with selections }
- IF GetScrap(NIL, 'TEXT', offset) > 0 THEN
- paste := TRUE; { Paste is enabled for app. windows }
-
- selectAll := TRUE;
- doPrint := TRUE;
-
- mode := doFace;
- menu := GetMHandle(mStyle);
- IF TEContinuousStyle(mode, gTxStyle, DocumentPeek(window)^.docTE) THEN BEGIN
- CheckItem(menu, iPlain, gTxStyle.tsface = []);
- CheckItem(menu, iBold, bold IN gTxStyle.tsFace);
- CheckItem(menu, iItalic, italic IN gTxStyle.tsFace);
- CheckItem(menu, iUnderline, underline IN gTxStyle.tsFace);
- CheckItem(menu, iOutline, outline IN gTxStyle.tsFace);
- CheckItem(menu, iShadow, shadow IN gTxStyle.tsFace);
- END
- ELSE BEGIN
- CheckItem(menu, iPlain, FALSE);
- CheckItem(menu, iBold, FALSE);
- CheckItem(menu, iItalic, FALSE);
- CheckItem(menu, iUnderline, FALSE);
- CheckItem(menu, iOutline, FALSE);
- CheckItem(menu, iShadow, FALSE);
- END; { if }
-
- END; { if }
- menu := GetMHandle(mEdit);
-
- IF undo THEN
- EnableItem(menu, iUndo)
- ELSE
- DisableItem(menu, iUndo);
-
- IF cutCopyClear THEN BEGIN
- EnableItem(menu, iCut);
- EnableItem(menu, iCopy);
- EnableItem(menu, iClear);
- END
- ELSE BEGIN
- DisableItem(menu, iCut);
- DisableItem(menu, iCopy);
- DisableItem(menu, iClear);
- END; { if }
-
-
- IF paste THEN
- EnableItem(menu, iPaste)
- ELSE
- DisableItem(menu, iPaste);
-
- IF selectAll THEN
- EnableItem(menu, iSelectAll)
- ELSE
- DisableItem(menu, iSelectAll);
-
-
- menu := GetMHandle(mFile);
- IF doPrint THEN BEGIN
- EnableItem(menu, iPageSetup);
- EnableItem(menu, iPrint);
- END
- ELSE BEGIN
- DisableItem(menu, iPageSetup);
- DisableItem(menu, iPrint);
- END; { if }
-
- END; { AdjustMenus }
-
- {$S Main}
- PROCEDURE DoMenuCommand (menuResult: LONGINT);
-
- { This is called when an item is chosen from the menu bar (after calling}
- { MenuSelect or MenuKey). It does the right thing for each command. }
-
- VAR
- menuID, menuItem: INTEGER;
- itemHit, daRefNum: INTEGER;
- daName: Str255;
-
- tempStr: Str255;
- menu: MenuHandle;
- anIntPtr: ^INTEGER;
-
- ignoreResult, saveErr: OSErr;
- handledByDA: BOOLEAN;
- te: TEHandle;
- window: WindowPtr;
- ignore: BOOLEAN;
- aHandle: Handle;
- oldSize, newSize: LONGINT;
- total, contig: LONGINT;
-
-
- BEGIN
- window := FrontWindow;
- menuID := HiWrd(menuResult); { use built-ins (for efficiency)... }
- menuItem := LoWrd(menuResult); { to get menu item number and menu number }
- te := DocumentPeek(window)^.docTE;
-
- CASE menuID OF
-
- mApple:
- CASE menuItem OF
- iAbout: {bring up alert for About}
- itemHit := Alert(rAboutAlert, NIL);
- OTHERWISE
- BEGIN { all non-About items in this menu are DAs }
- GetItem(GetMHandle(mApple), menuItem, daName);
- daRefNum := OpenDeskAcc(daName);
- END; { otherwise }
- END; { case }
-
- mFile:
- CASE menuItem OF
- iNew:
- DoNew;
- iOpen:
- BEGIN
- SetCursor(GetCursor(watchCursor)^^);
- DoOpen;
- END;
-
- iClose:
- ignore := DoCloseWindow(window);
-
- iSave:
- DoSave(FALSE);
-
- iSaveAs:
- DoSave(TRUE);
-
- iPageSetup:
- BEGIN
- PrOpen;
- IF PrError = noErr THEN
- ignore := PrStlDialog(gPrinterRecord);
- PrClose;
- END; { iPageSetup }
- iPrint:
- PrintText(te);
- iQuit:
- Terminate;
- END; { case }
-
- mEdit:
- BEGIN { call SystemEdit for DA editing & MultiFinder }
- IF NOT SystemEdit(menuItem - 1) THEN BEGIN
- CASE menuItem OF
-
- iCut:
- BEGIN
- IF ZeroScrap = noErr THEN BEGIN
- PurgeSpace(total, contig);
- IF (te^^.selEnd - te^^.selStart) + kTESlop > contig THEN
- AlertUser(eNoSpaceCut,0)
- ELSE BEGIN
- TECut(te);
- END; { if }
- END; { if }
- END; { iCut }
-
- iCopy:
- BEGIN
- IF ZeroScrap = noErr THEN BEGIN
- TECopy(te);
- END; { if }
- END; { iCopy }
-
- iPaste:
- BEGIN
- IF TEGetScrapLen + (te^^.teLength - (te^^.selEnd - te^^.selStart)) > kMaxTELength THEN
- AlertUser(eExceedPaste,0)
- ELSE BEGIN
- aHandle := Handle(TEGetText(te));
- oldSize := GetHandleSize(aHandle);
- newSize := oldSize + TEGetScrapLen + kTESlop;
- SetHandleSize(aHandle, newSize);
- saveErr := MemError;
- SetHandleSize(aHandle, oldSize);
- IF saveErr <> noErr THEN
- AlertUser(eNoSpacePaste,0)
- ELSE
- TEStylPaste(te);
- END; { if }
- END; { iPaste }
-
- iClear:
- TEDelete(te);
-
- iSelectAll:
- TESetSelect(0, te^^.teLength, te);
-
- END; { case }
- IF menuItem <> iCopy THEN
- AdjustScrollBars(window, FALSE);
- END; { if }
- END; { mEdit }
-
- mFont:
- BEGIN { mFont }
- GetItem(GetMHandle(mFont), menuItem, gFontName);
- getFNum(gFontName, gFontID);
- gTxStyle.tsFont := gFontID;
- TESetStyle(doFont, gTxStyle, true, te);
- AdjustScrollBars(window, FALSE);
- END; { mFont }
-
- mFontSize:
- BEGIN { mFontSize }
- CASE menuItem OF
- iNine:
- gFontSize := 9;
- iTen:
- gFontSize := 10;
- iTwelve:
- gFontSize := 12;
- iFourteen:
- gFontSize := 14;
- iEighteen:
- gFontSize := 18;
- iTwoFour:
- gFontSize := 24;
- iOther:
- gFontSize := GetNewFontSize;
- END; { case }
- gTxStyle.tsSize := gFontSize;
- TESetStyle(doSize, gTxStyle, TRUE, te);
- AdjustScrollBars(window, FALSE);
- END; { mFontSize }
-
- mStyle:
- BEGIN { mStyle }
- WITH gTxStyle DO BEGIN
- CASE menuItem OF
- iPlain:
- BEGIN
- anIntPtr := @gTxStyle.tsFace; { as per Tech Note #131 }
- anIntPtr^ := 0;
- tsFace := [];
- END;
- iBold:
- tsFace := [bold];
- iItalic:
- tsFace := [italic];
- iUnderline:
- tsFace := [underline];
- iOutline:
- tsFace := [outline];
- iShadow:
- tsFace := [shadow];
- END; { case }
-
- IF menuItem <> 1 THEN
- TESetStyle(doFace + doToggle, gTxStyle, TRUE, te)
- { if we don't select plain then use doToggle }
- ELSE
- TESetStyle(doFace, gTxStyle, TRUE, te);
- { TESetStyle has problems with plain and doToggle-has no effect!}
- { so we need to special case it. }
- AdjustScrollBars(window, FALSE);
- END; { with }
- END; { mStyle }
-
- END; { case }
- HiliteMenu(0); { unhighlight what MenuSelect (or MenuKey) hilited }
- END; { DoMenuCommand }
-
- {$S Main}
- PROCEDURE DrawWindow (window: WindowPtr);
-
- { Draw the contents of an application window. }
-
- BEGIN { DrawWindow }
- SetPort(window);
- WITH window^ DO BEGIN
- EraseRect(portRect); { as per TextEdit chapter of Inside Macintosh }
- DrawControls(window); { this ordering makes for a better appearance }
- DrawGrowIcon(window);
- TEUpdate(portRect, DocumentPeek(window)^.docTE);
- END; { with }
- END; { DrawWindow }
-
- {$S Main}
- FUNCTION GetSleep: LONGINT;
-
- { Calculate a sleep value for WaitNextEvent. This takes into account the things}
- { that DoIdle does with idle time. }
-
- VAR
- sleep: LONGINT;
- window: WindowPtr;
-
- BEGIN { GetSleep }
- sleep := MAXLONGINT; { default value for sleep }
- IF NOT gInBackground THEN BEGIN { if we are in front... }
- window := FrontWindow; { and the front window is ours... }
- IF IsAppWindow(window) THEN BEGIN
- WITH DocumentPeek(window)^.docTE^^ DO
- IF selStart = selEnd THEN { and the selection is an insertion point... }
- sleep := GetCaretTime; { we need to blink the insertion point }
- END; { if }
- END; { if }
- GetSleep := sleep;
- END; { GetSleep }
-
- {$S Main}
- PROCEDURE CommonAction (control: ControlHandle; VAR amount: INTEGER);
-
- { Common algorithm for setting the new value of a control. It returns the actual amount}
- { the value of the control changed. Note the pinning is done for the sake of returning}
- { the amount the control value changed. }
-
- VAR
- value, max: INTEGER;
- window: WindowPtr;
-
- BEGIN { CommonAction }
- value := GetCtlValue(control); { get current value }
- max := GetCtlMax(control); { and max value }
- amount := value - amount;
- IF amount < 0 THEN
- amount := 0
- ELSE IF amount > max THEN
- amount := max;
- SetCtlValue(control, amount);
- amount := value - amount; { calculate true change }
- END; { CommonAction }
-
- {$S Main}
- PROCEDURE VActionProc (control: ControlHandle; part: INTEGER);
-
- { Determines how much to change the value of the vertical scrollbar by and how}
- { much to scroll the TE record. }
-
- VAR
- amount: INTEGER;
- window: WindowPtr;
-
- BEGIN { VActionProc }
- IF part <> 0 THEN BEGIN
- window := control^^.contrlOwner;
- WITH DocumentPeek(window)^, DocumentPeek(window)^.docTE^^ DO BEGIN
- CASE part OF
- inUpButton, inDownButton:
- amount := 24;
- inPageUp, inPageDown:
- amount := viewRect.bottom - viewRect.top; { one page }
- END; { case }
- IF (part = inDownButton) | (part = inPageDown) THEN
- amount := -amount; { reverse direction }
- CommonAction(control, amount);
- IF amount <> 0 THEN
- TEScroll(0, amount, docTE);
- END; { with }
- END; { if }
- END; { VActionProc }
-
- {$S Main}
- PROCEDURE HActionProc (control: ControlHandle; part: INTEGER);
-
- { Determines how much to change the value of the horizontal scrollbar by and how}
- { much to scroll the TE record. }
-
- VAR
- amount: INTEGER;
- window: WindowPtr;
-
- BEGIN { HActionProc }
- IF part <> 0 THEN BEGIN
- window := control^^.contrlOwner;
- WITH DocumentPeek(window)^, DocumentPeek(window)^.docTE^^ DO BEGIN
- CASE part OF
- inUpButton, inDownButton:
- amount := kButtonScroll; { a few pixels }
- inPageUp, inPageDown:
- amount := viewRect.right - viewRect.left; { a page }
- END; { case }
- IF (part = inDownButton) | (part = inPageDown) THEN
- amount := -amount; { reverse direction }
- CommonAction(control, amount);
- IF amount <> 0 THEN
- TEScroll(amount, 0, docTE);
- END; { with }
- END; { if }
- END; { HActionProc }
-
- {$S Main}
- PROCEDURE DoIdle;
-
- { This is called whenever we get an null event or a mouse-moved event.}
- { It takes care of necessary periodic actions. For this program, it calls TEIdle. }
-
- VAR
- window: WindowPtr;
-
- BEGIN { DoIdle }
- window := FrontWindow;
- IF IsAppWindow(window) THEN
- TEIdle(DocumentPeek(window)^.docTE);
- END; { DoIdle }
-
- {$S Main}
- PROCEDURE DoKeyDown (event: EventRecord);
-
- { This is called for any keyDown or autoKey events, except when the}
- { Command key is held down. It looks at the frontmost window to decide what}
- { to do with the key typed. }
-
- VAR
- window: WindowPtr;
- key: CHAR;
- te: TEHandle;
-
- BEGIN
- window := FrontWindow;
- IF IsAppWindow(window) THEN BEGIN
- te := DocumentPeek(window)^.docTE;
- key := CHR(BAnd(event.message, charCodeMask));
- IF (key = CHR(kDelChar)) | (te^^.teLength - (te^^.selEnd - te^^.selStart) + 1 < kMaxTELength) THEN { don't count deletes }
- BEGIN { but check haven't gone past }
- TEKey(key, te);
- AdjustScrollbars(window, FALSE);
- END
- ELSE
- AlertUser(eExceedChar,0);
- END; { if }
- END; { DoKeyDown }
-
- {$S Main}
- PROCEDURE DoContentClick (window: WindowPtr; event: EventRecord);
-
- { Called when a mouseDown occurs in the content of a window. }
-
- VAR
- mouse: Point;
- control: ControlHandle;
- part, value: INTEGER;
- shiftDown: BOOLEAN;
- teRect: Rect;
-
- BEGIN { DoContentClick }
- IF IsAppWindow(window) THEN BEGIN
- SetPort(window);
- mouse := event.where; { get the click position }
- GlobalToLocal(mouse); { convert to local coordinates }
-
- GetTERect(window, teRect);
- IF PtInRect(mouse, teRect) THEN BEGIN
- shiftDown := BAnd(event.modifiers, shiftKey) <> 0; { extend if Shift is down }
- TEClick(mouse, shiftDown, DocumentPeek(window)^.docTE);
- END
- ELSE BEGIN
- part := FindControl(mouse, window, control);
- WITH DocumentPeek(window)^ DO
- CASE part OF
- 0:
- ; { do nothing for viewRect case }
- inThumb:
- BEGIN
- value := GetCtlValue(control);
- part := TrackControl(control, mouse, NIL);
- IF part <> 0 THEN BEGIN
- value := value - GetCtlValue(control);
- IF value <> 0 THEN
- IF control = docVScroll THEN
- TEScroll(0, value, docTE)
- ELSE
- TEScroll(value, 0, docTE);
- END; { if }
- END; { inThumb }
- OTHERWISE { must be page or button }
- IF control = docVScroll THEN
- value := TrackControl(control, mouse, @VActionProc)
- ELSE
- value := TrackControl(control, mouse, @HActionProc);
- END; { case }
- END; { if }
- END; { if }
- END; { DoContentClick }
-
- {$S Main}
- PROCEDURE ResizeWindow (window: WindowPtr);
-
- { Called when the window has been resized to fix up the controls and content }
-
- BEGIN { ResizeWindow }
- WITH window^ DO BEGIN
- AdjustScrollbars(window, TRUE);
- AdjustTE(window);
- InvalRect(portRect);
- END;
- END; { ResizeWindow }
-
- {$S Main}
- PROCEDURE GetLocalUpdateRgn (window: WindowPtr; localRgn: RgnHandle);
-
- { Returns the update region in local coordinates }
-
- BEGIN { GetLocalUpdateRgn }
- CopyRgn(WindowPeek(window)^.updateRgn, localRgn); { save old update region }
- WITH window^.portBits.bounds DO
- OffsetRgn(localRgn, left, top); { convert to local coords }
- END; { GetLocalUpdateRgn }
-
- {$S Main}
- PROCEDURE DoGrowWindow (window: WindowPtr; event: EventRecord);
-
- { Called when a mouseDown occurs in the grow box of an active window. In}
- { order to eliminate any 'flicker', we want to invalidate only what is}
- { necessary. Since ResizeWindow invalidates the whole portRect, we save}
- { the old TE viewRect, intersect it with the new TE viewRect, and}
- { remove the result from the update region. However, we must make sure}
- { that any old update region that might have been around gets put back. }
-
- VAR
- growResult: LONGINT;
- tempRect: Rect;
- tempRgn: RgnHandle;
- ignoreResult: BOOLEAN;
-
- BEGIN { DoGrowWindow }
- WITH screenBits.bounds DO
- SetRect(tempRect, kMinDocDim, kMinDocDim, right, bottom); { set up limiting values }
- growResult := GrowWindow(window, event.where, tempRect);
- IF growResult <> 0 THEN { see if changed size }
- WITH DocumentPeek(window)^, window^ DO BEGIN
- tempRect := docTE^^.viewRect; { save old text box }
- tempRgn := NewRgn;
- GetLocalUpdateRgn(window, tempRgn); { get localized update region }
- SizeWindow(window, LoWrd(growResult), HiWrd(growResult), TRUE);
- ResizeWindow(window);
- ignoreResult := SectRect(tempRect, docTE^^.viewRect, tempRect); { find what stayed same }
- ValidRect(tempRect); { take it out of update }
- InvalRgn(tempRgn); { put back any prior update }
- DisposeRgn(tempRgn);
- END; { with }
- END; { DoGrowWindow }
-
- {$S Main}
- PROCEDURE DoZoomWindow (window: WindowPtr; part: INTEGER);
-
- { Called when a mouseClick occurs in the zoom box of an active window.}
- { Everything has to get re-drawn here, so we don't mind that}
- { ResizeWindow invalidates the whole portRect. }
-
- BEGIN { DoZoomWindow }
- WITH window^ DO BEGIN
- EraseRect(portRect);
- ZoomWindow(window, part, (window = FrontWindow));
- ResizeWindow(window);
- END; { with }
- END; { DoZoomWindow }
-
- {$S Main}
- PROCEDURE DoUpdate (window: WindowPtr);
-
- { This is called when an update event is received for a window.}
- { It calls DrawWindow to draw the contents of an application window,}
- { but only if the visRgn is non-empty; for efficiency reasons,}
- { not because it is required. }
-
- BEGIN { DoUpdate }
- IF IsAppWindow(window) THEN BEGIN
- BeginUpdate(window); { this sets up the visRgn }
- IF NOT EmptyRgn(window^.visRgn) THEN { draw if updating needs to be done }
- DrawWindow(window);
- EndUpdate(window);
- END; { if }
- END; { DoUpdate }
-
- {$S Main}
- PROCEDURE DoActivate (window: WindowPtr; becomingActive: BOOLEAN);
-
- { This is called when a window is activated or deactivated. }
-
- VAR
- tempRgn, clipRgn: RgnHandle;
- growRect: Rect;
-
- BEGIN { DoActivate }
- IF IsAppWindow(window) THEN
- WITH DocumentPeek(window)^ DO
- IF becomingActive THEN BEGIN
- { since we don’t want TEActivate to draw a selection in an area where}
- { we’re going to erase and redraw, we’ll clip out the update region}
- { before calling it. }
- tempRgn := NewRgn;
- clipRgn := NewRgn;
- GetLocalUpdateRgn(window, tempRgn); { get localized update region }
- GetClip(clipRgn);
- DiffRgn(clipRgn, tempRgn, tempRgn); { subtract updateRgn from clipRgn }
- SetClip(tempRgn);
- TEActivate(docTE); { let TE do its thing }
- SetClip(clipRgn); { restore the full-blown clipRgn }
- DisposeRgn(tempRgn);
- DisposeRgn(clipRgn);
-
- {the controls need to be redrawn on activation:}
- docVScroll^^.contrlVis := kControlVisible;
- docHScroll^^.contrlVis := kControlVisible;
- InvalRect(docVScroll^^.contrlRect);
- InvalRect(docHScroll^^.contrlRect);
- { the growbox needs to be redrawn on activation: }
- growRect := window^.portRect;
- WITH growRect DO BEGIN
- top := bottom - kScrollbarAdjust; { adjust for the scrollbars }
- left := right - kScrollbarAdjust;
- END; { with }
- InvalRect(growRect);
- END
- ELSE BEGIN
- TEDeactivate(docTE);
- { the controls should be hidden immediately on deactivation: }
- HideControl(docVScroll);
- HideControl(docHScroll);
- { the growbox should be changed immediately on deactivation: }
- DrawGrowIcon(window);
- END; { if }
- END; { DoActivate }
-
- {$S Main}
- PROCEDURE GetGlobalMouse (VAR mouse: Point);
-
- {Get the global coordinates of the mouse. When you call OSEventAvail}
- { it will return either a pending event or a null event. In either case,}
- { the where field of the event record will contain the current position}
- { of the mouse in global coordinates and the modifiers field will reflect}
- { the current state of the modifiers. Another way to get the global}
- { coordinates is to call GetMouse and LocalToGlobal, but that requires}
- { being sure that thePort is set to a valid port.}
-
- VAR
- event: EventRecord;
-
- BEGIN
- IF OSEventAvail(kNoEvents, event) THEN
- ; {we aren't interested in any events}
- mouse := event.where; {just the mouse position}
- END;
-
- {$S Main}
- PROCEDURE AdjustCursor (mouse: Point; region: RgnHandle);
-
- { Change the cursor's shape, depending on its position. This also calculates a region}
- { that includes the cursor for WaitNextEvent. }
-
- VAR
- window: WindowPtr;
- arrowRgn: RgnHandle;
- iBeamRgn: RgnHandle;
- iBeamRect: Rect;
-
- BEGIN { AdjustCursor }
- window := FrontWindow; { we only adjust the cursor when we are in front }
- IF (NOT gInBackground) AND (NOT IsDAWindow(window)) THEN BEGIN
- { calculate regions for different cursor shapes}
- arrowRgn := NewRgn;
- iBeamRgn := NewRgn;
-
- { start with a big, big rectangular region }
- SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
-
- { calculate iBeamRgn }
- IF IsAppWindow(window) THEN BEGIN
- iBeamRect := DocumentPeek(window)^.docTE^^.viewRect;
- SetPort(window); { make a global version of the viewRect }
- WITH iBeamRect DO BEGIN
- LocalToGlobal(topLeft);
- LocalToGlobal(botRight);
- END; { with }
- RectRgn(iBeamRgn, iBeamRect);
- WITH window^.portBits.bounds DO
- SetOrigin(-left, -top);
- SectRgn(iBeamRgn, window^.visRgn, iBeamRgn);
- SetOrigin(0, 0);
- END; { if }
-
- { subtract other regions from arrowRgn }
- DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
-
- {change the cursor and the region parameter}
- IF PtInRgn(mouse, iBeamRgn) THEN BEGIN
- SetCursor(GetCursor(iBeamCursor)^^);
- CopyRgn(iBeamRgn, region);
- END
- ELSE BEGIN
- SetCursor(arrow);
- CopyRgn(arrowRgn, region);
- END; { if }
-
- { get rid of our local regions }
- DisposeRgn(arrowRgn);
- DisposeRgn(iBeamRgn);
- END; { if }
- END; { AdjustCursor }
-
- {$S Main}
- PROCEDURE DoEvent (event: EventRecord);
-
- { Do the right thing for an event. Determine what kind of event it is, and call}
- { the appropriate routines. }
-
- VAR
- part, err: INTEGER;
- window: WindowPtr;
- key: CHAR;
- ignore: BOOLEAN;
- aPoint: Point;
-
- BEGIN { DoEvent }
- CASE event.what OF
- nullEvent:
- DoIdle;
- mouseDown:
- BEGIN
- part := FindWindow(event.where, window);
- CASE part OF
-
- inMenuBar:
- BEGIN
- AdjustMenus;
- DoMenuCommand(MenuSelect(event.where));
- END; { inMenuBar }
-
- inSysWindow:
- SystemClick(event, window);
-
- inContent:
- IF window <> FrontWindow THEN BEGIN
- SelectWindow(window);
- {DoEvent(event);}
- {use this line for "do first click"}
- END
- ELSE
- DoContentClick(window, event);
-
- inDrag:
- DragWindow(window, event.where, screenBits.bounds);
-
- inGrow:
- DoGrowWindow(window, event);
-
- inGoAway:
- IF TrackGoAway(window, event.where) THEN
- ignore := DoCloseWindow(window); { we don't care if cancelled }
-
- inZoomIn, inZoomOut:
-
- IF TrackBox(window, event.where, part) THEN
- DoZoomWindow(window, part);
- END; { case }
- END; { mouseDown }
-
- keyDown, autoKey:
- BEGIN
- key := CHR(BAnd(event.message, charCodeMask));
- IF BAnd(event.modifiers, cmdKey) <> 0 THEN BEGIN { Command key down }
- IF event.what = keyDown THEN BEGIN
- AdjustMenus; { enable/disable/check menu items properly }
- DoMenuCommand(MenuKey(key));
- END; { if }
- END
- ELSE
- DoKeyDown(event);
- END; { keyDown }
- { call DoActivate with the window and... }
-
- activateEvt: { TRUE for activate, FALSE for deactivate }
- DoActivate(WindowPtr(event.message), BAND(event.modifiers, activeFlag) <> 0);
-
- updateEvt: { call DoUpdate with the window to update }
- DoUpdate(WindowPtr(event.message));
-
- diskEvt:
- IF HiWrd(event.message) <> noErr THEN BEGIN
- SetPt(aPoint, kDILeft, kDITop);
- err := DIBadMount(aPoint, event.message);
- END;
-
- kOSEvent:
- CASE BAnd(BRotL(event.message, 8), $FF) OF { high byte of message }
- kMouseMovedMessage:
- DoIdle; { mouse moved is also an idle event }
-
- kSuspendResumeMessage:
- BEGIN
- gInBackground := BAnd(event.message, kResumeMask) = 0;
- DoActivate(FrontWindow, NOT gInBackground);
- END; { kSuspendResumeMessage }
- END;
- END; { case }
- END; { DoEvent }
-
- {$S Main}
- PROCEDURE EventLoop;
-
- { Get events forever, and handle them by calling DoEvent.}
- { Also call AdjustCursor each time through the loop. }
-
- VAR
- cursorRgn: RgnHandle;
- gotEvent: BOOLEAN;
- event: EventRecord;
- mouse: Point;
-
- BEGIN { EventLoop }
- cursorRgn := NewRgn; { we'll pass an empty region to WNE the first time thru }
- REPEAT
- IF gHasWaitNextEvent THEN BEGIN
- GetGlobalMouse(mouse); {since we might go to sleep}
- AdjustCursor(mouse, cursorRgn);
- gotEvent := WaitNextEvent(everyEvent, event, GetSleep, cursorRgn)
- END
- ELSE BEGIN
- SystemTask;
- gotEvent := GetNextEvent(everyEvent, event);
- END; { if }
- IF gotEvent THEN BEGIN
- AdjustCursor(event.where, cursorRgn);
- DoEvent(event);
- END
- ELSE
- DoIdle;
- UNTIL FALSE; { loop forever }
- END; { EventLoop }
-
- PROCEDURE _DataInit;
- EXTERNAL;
-
- { This routine is automatically linked in by the MPW Linker. This external}
- { reference to it is done so that we can unload its segment, %A5Init. }
-
- {$S Main}
- BEGIN { main program }
- UnloadSeg(@_DataInit); { note that _DataInit must not be in Main! }
- MaxApplZone; { expand the heap so code segments load at the top }
- Initialize; { initialize the program }
- UnloadSeg(@Initialize); { note that Initialize must not be in Main! }
- EventLoop; { call the main event loop }
- END. { main program }